package com.speljohan.rsbot.account;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

public class AccountHandler {
	private final Set<Account> accounts = new HashSet<Account>();
	private final File store;
	private final Logger log = Logger.getLogger(AccountHandler.class.getName());
	private final String tokenAssign = "=";
	private final String tokenDelim = ",";

	public AccountHandler(final File workDir) {
		store = new File(new File(workDir, "Settings"), "Accounts.ini");
		loadAccounts();
	}

	public void addAccount(final Account a) {
		accounts.add(a);
	}

	public void clearAccounts() {
		accounts.clear();
	}

	public Set<Account> getAccounts() {
		return Collections.unmodifiableSet(accounts);
	}

	private void loadAccounts() {
		if (!store.exists()) {
			log.info("No accounts to load.");
			return;
		}

		int corrupt = 0;

		try {
			final BufferedReader reader = new BufferedReader(new FileReader(
					store));
			String line;

			while ((line = reader.readLine()) != null) {
				if (log.isLoggable(Level.FINE)) {
					log.fine("Reading line: /" + line + "/");
				}

				final Account a = new Account();
				for (final String pair : line.split(tokenDelim)) {
					final String[] val = pair.split(tokenAssign, 2);

					if (log.isLoggable(Level.FINE)) {
						log.fine("key: " + val[0] + " val: " + val[1]);
					}

					a.addProperty(val[0], val[1]);
				}
				if (a.isValid()) {
					accounts.add(a);
				} else {
					corrupt++;
					log.fine("Account was invalid." + a);
				}
			}

			reader.close();
		} catch (final IOException e) {
			log.severe("Failed to load accounts.");
			e.printStackTrace();
		}

		if (corrupt != 0) {
			log.severe(corrupt + " malformed lines found in accounts file.");
		}

		log.info("Loaded " + accounts.size() + " accounts.");
	}

	public void removeAccount(final Account a) {
		accounts.remove(a);
	}

	public void syncAccounts() {
		if (store.exists()) {
			log.info("Purging accounts file.");
			if (!store.delete()) {
				log.severe("Unable to replace existing log file.");
				return;
			}
		}

		int saved = 0;

		try {
			if (!store.createNewFile()) {
				log.severe("Unable to create accounts file.");
				return;
			}

			final BufferedWriter writer = new BufferedWriter(new FileWriter(
					store));

			for (final Account a : accounts) {
				final Map<String, String> props = a.getAllProperties();
				for (final String key : props.keySet()) {
					writer.write(key);
					writer.write(tokenAssign);
					writer.write(props.get(key));
					writer.write(tokenDelim);
				}
				writer.newLine();
				saved++;
			}

			writer.close();
		} catch (final IOException e) {
			log.severe("Failed to save accounts.");
			e.printStackTrace();
		}

		log.info("Saved " + Integer.toString(saved) + " accounts.");
	}
}
